﻿using System.Collections.Immutable;

namespace DimensionsHelper.SourceGeneration.CommandLine
{

    /// <summary>
    /// 记录生成器待生成的所有内容
    /// </summary>
    public sealed class GenerationInfo
    {

        public GenerationInfo(string @namespace, string contextClassName, ObjectGenerationInfo[] objects, bool isInternal)
        {
            Namespace = @namespace;
            ContextClassName = contextClassName;
            Objects = objects.ToImmutableArray();
            IsInternal = isInternal;
        }


        /// <summary>
        /// 当前代码的命名空间名
        /// </summary>
        public string Namespace { get; set; }

        /// <summary>
        /// 带有 ArgumentContextAttribute 注解的原始类型名
        /// </summary>
        public string ContextClassName { get; set; }

        /// <summary>
        /// 如果<see cref="ContextClassName"/>所指类型是internal的，将此属性设置为<see langword="true"/>
        /// </summary>
        public bool IsInternal { get; set; }

        /// <summary>
        /// 待生成的对象列表
        /// </summary>
        public ImmutableArray<ObjectGenerationInfo> Objects { get; set; }
    }


    /// <summary>
    /// 记录生成器对象信息
    /// </summary>
    public sealed class ObjectGenerationInfo
    {

        /// <summary>
        /// 当前代码的命名空间名
        /// </summary>
        public string Namespace { get; set; }

        /// <summary>
        /// 上下文类名
        /// </summary>
        public string ContextClassName { get; set; }

        /// <summary>
        /// 如果<see cref="ContextClassName"/>所指类型是internal的，将此属性设置为<see langword="true"/>
        /// </summary>
        public bool IsInternal { get; set; }

        /// <summary>
        /// 带有 ArgumentObjectAttribute 注解的原始类型名
        /// </summary>
        public string TypeName { get; set; }

        /// <summary>
        /// 带有 ArgumentObjectAttribute 注解的原始类型全名
        /// </summary>
        public string TypeFullName { get; set; }

        /// <summary>
        /// 类型的非字典类型属性列表
        /// </summary>
        public ImmutableArray<ObjectPropertyGenerationInfo> RegularProperties { get; set; }

        /// <summary>
        /// 类型的字典类型属性列表
        /// </summary>
        public ImmutableArray<ObjectDictionaryPropertyGenerationInfo> DictionaryProperties { get; set; }
    }


    /// <summary>
    /// 记录使用 ArgumentObjectAttribute 注解标注在 ArgumentContext 派生类上的待生成类型。
    /// </summary>
    public sealed class ObjectPropertyGenerationInfo
    {

        /// <summary>
        /// 此属性所在类型名
        /// </summary>
        public string ClassName { get; set; }

        /// <summary>
        /// 此属性所在的类型全名
        /// </summary>
        public string ClassFullName { get; set; }

        /// <summary>
        /// 属性名
        /// </summary>
        public string PropertyName { get; set; }

        /// <summary>
        /// 控制台参数名
        /// </summary>
        public string ArgumentName { get; set; }

        /// <summary>
        /// 列表值字符串分隔符
        /// </summary>
        public string ListSeparator { get; set; }

        /// <summary>
        /// 简单的类型名
        /// </summary>
        public string TypeName { get; set; }

        /// <summary>
        /// 属性的赋值实现类型
        /// </summary>
        public string ImplTypeFullName { get; set; }

        /// <summary>
        /// 属性的原始类型，可能是接口类型
        /// </summary>
        public string OriginalTypeFullName { get; set; }

        /// <summary>
        /// 当属性值类型是对象类型，将绑定的属性名配置到此属性
        /// </summary>
        public string PropertyBinding { get; set; }

        /// <summary>
        /// 指示属性类型是否是基础类型
        /// </summary>
        public bool IsBasicType { get; set; }

        /// <summary>
        /// 指示属性类型是否是列表类型
        /// </summary>
        public bool IsList { get; set; }

        /// <summary>
        /// 指示属性是否是字典属性的关键字参数
        /// </summary>
        public bool IsDictionaryKey { get; set; }

        /// <summary>
        /// 指示属性是否是字典属性的值参数
        /// </summary>
        public bool IsDictionaryValue { get; set; }

        /// <summary>
        /// 指示属性是否是只读的
        /// </summary>
        public bool IsReadOnly { get; set; }

        /// <summary>
        /// 指示属性是否是只写的
        /// </summary>
        public bool IsWriteOnly { get; set; }

        /// <summary>
        /// 当属性类型值是对象时，设置此属性为<see langword="true"/>
        /// </summary>
        public bool IsObjectRef { get; set; }

        /// <summary>
        /// 当属性值类型是列表时，将元素类型配置到此属性值
        /// </summary>
        public string ListElementType { get; set; }

        /// <summary>
        /// 当属性类型是对象或列表，并且通过多个注解绑定参数时，将普通参数设置到此属性
        /// </summary>
        public ImmutableArray<ObjectPropertyGenerationInfo> ObjectProperties { get; set; }

        /// <summary>
        /// 当属性类型是对象或列表，并且通过多个注解绑定参数时，将字典参数设置到此属性
        /// </summary>
        public ImmutableArray<ObjectDictionaryPropertyGenerationInfo> ObjectDictionaryProperties { get; set; }

        /// <summary>
        /// 当此属性的<see cref="ObjectProperties"/>不是null并且列表长度大于0时，
        /// 如果此属性值允许沿用上一个有效值，将此属性设置为<see langword="true"/>
        /// </summary>
        public bool CanFollow { get; set; }
    }


    /// <summary>
    /// 记录字典类型属性的属性生成信息。
    /// </summary>
    public sealed class ObjectDictionaryPropertyGenerationInfo
    {

        /// <summary>
        /// 字典属性所在的对象类型名
        /// </summary>
        public string ClassName { get; set; }

        /// <summary>
        /// 字典属性所在的对象类型全名
        /// </summary>
        public string ClassFullName { get; set; }

        /// <summary>
        /// 字典属性名
        /// </summary>
        public string PropertyName { get; set; }

        /// <summary>
        /// 字典原始类型
        /// </summary>
        public string DictionaryType { get; set; }

        /// <summary>
        /// 字典属性的实现类型名
        /// </summary>
        public string DictionaryValueType { get; set; }

        /// <summary>
        /// 指示属性是否是只读的
        /// </summary>
        public bool IsReadOnly { get; set; }

        /// <summary>
        /// 指示属性是否是只写的
        /// </summary>
        public bool IsWriteOnly { get; set; }

        /// <summary>
        /// 字段关键字属性
        /// </summary>
        public ObjectPropertyGenerationInfo Key { get; set; }

        /// <summary>
        /// 字段值属性
        /// </summary>
        public ObjectPropertyGenerationInfo Value { get; set; }
    }


}